package com.anuo.app.study.studyjava;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;

import java.util.ArrayList;
import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = {"classpath:spring/spring-context.xml"})

/**
 * Java 泛型
 * 研究状态: 常用已完成
 * 应用场景: 在类型不明的地方使用
 *
 * @ 泛型类
 * @ 泛型方法
 * java 泛型方法的T在参数中明确,so 在定义方法的时候,  参数中至少要有一个T
 * @ 有界限的类型参数(有界限的T)
 * @ 类型通配符
 */
public class StudyGenerics {
    public static void main(String[] args) {
        //泛型方法调用
        //String[] strArray={"hello","world"};
        //genericStaticMethod(strArray);
        //有界限的T
        //boundedTypeParameter(1);
        //类型通配符
        List<String> lists = new ArrayList<>();
        lists.add("anuo");
        List<Double> listd = new ArrayList<>();
        listd.add(12.2);
        List<Integer> listI = new ArrayList<>();
        listI.add(1);
        wildcard(listI);
        wildcard(listd);
        wildcard(lists);
    }

    //泛型方法(静态)
    public static <T> String genericStaticMethod(T[] array) {
        for (T item : array) {
            String s = item.toString();
            System.out.println(s);
        }
        return "";
    }

    //泛型方法(无返回值)
    public <T> void genericMethod(T[] array) {
        //和泛型静态方法的区别是 , T 放在 public 上, 静态方法是放在static 上
    }

    //泛型方法(有返回值)
    public <T> T genericMethodB(List<T> listT) {
        T obj = null;
        return obj;
    }

    //有界限的类型参数
    public static <T extends Number> void boundedTypeParameter(T number) {
        String s = number.toString();
        //官方文档: https://docs.oracle.com/javase/tutorial/java/generics/bounded.html
    }

    //泛型类
    public static void genericClass() {
        StudyGenericClass<String> t = new StudyGenericClass<String>();
    }

    //类型通配符(一般不用)
    public static void wildcard(List<?> list) {
        System.out.println(list.get(0));
        //类型通配符和 T 的区别是 ? 不能作为类型使用 如下:
        //? a="1";
        //而且 通配符受到很多限制, 一般用T 而不是用通配符 https://stackoverflow.com/questions/18176594/when-to-use-generic-methods-and-when-to-use-wild-card

    }

    //class<?> vs class<T>
    // class<?> ? 是通配符, 接收任意类型,
    // class<T> T 是泛型T 接收具体类型
    // 文章参考: http://www.cnblogs.com/skyislimit/p/5665853.html
    public void studyClassGeneric() {
        //遇到 class<?> 参数如何传?用类.getClass来传,如下
        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
        //UserService userService = new UserService();
        //mapperScannerConfigurer.setAnnotationClass(userService.getClass());

    }

    //泛型类
    private static class StudyGenericClass<T> {

        private T t;

        public void add(T t) {
            this.t = t;
        }

        public T get() {
            return t;
        }

        public static void main(String[] args) {
            StudyGenericClass<Integer> integerBox = new StudyGenericClass<Integer>();
            StudyGenericClass<String> stringBox = new StudyGenericClass<String>();

            integerBox.add(new Integer(10));
            stringBox.add(new String("菜鸟教程"));

            System.out.printf("整型值为 :%d\n\n", integerBox.get());
            System.out.printf("字符串为 :%s\n", stringBox.get());
        }
    }


}
